﻿/**
 * Copyright (C) 2011 original author and authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace NGuice.Inject.Internal.Util
{
    /// <summary>
    /// TODO:为类及其成员查找行数的工具
    /// </summary>
    public class LineNumbers
    {
        private readonly Type type;

        private readonly IDictionary<string, int> lines = new Dictionary<string, int>();

        private string source;

        private int firstLine = int.MaxValue;

        public LineNumbers(Type type)
        {
            //TODO:从类型中读取每个方法的签名及其行数加入到缓存lines中！.NET中找不到好的库可以读取一个类型所在源文件中成员的行数
            this.type = type;
        }

        /// <summary>
        /// //TODO:源文件名称。NET中找不到号的库读取一个类型所在源文件
        /// </summary>
        public string Source
        {
            get
            {
                return source;
            }

        }

        /// <summary>
        /// 获取类型中给定成员关联的行号
        /// </summary>
        /// <param name="member"></param>
        /// <returns></returns>
        public int GetLineNumber(MemberInfo member)
        {
            Preconditions.CheckArgument(type == member.DeclaringType, "Member {0} belongs to {1}, not {2}", member, member.DeclaringType, type);
            string key = MemberKey(member);
            if (lines.ContainsKey(key))
                return lines[MemberKey(member)];
            return -1;
        }

        public int FirstLine
        {
            get
            {
                return firstLine == int.MaxValue ? 1 : firstLine;
            }
        }

        private string MemberKey(MemberInfo member)
        {
            Preconditions.CheckNotNull(member, "member");

            /*if[AOP]*/
            if (member is FieldInfo || member is PropertyInfo)
            {
                return member.Name;

            }
            else if (member is MethodInfo)
            {
                return Classes.GetMethodDescriptor(member as MethodInfo);
            }
            else if (member is ConstructorInfo)
            {
                return Classes.GetConstructorDescriptor(member as ConstructorInfo);
            }
            else
            {
                throw new ArgumentException(
                    "Unsupported implementation class for Member, " + member.DeclaringType);
            }
            /*end[AOP]*/
            /*if[NO_AOP]
            return "<NO_MEMBER_KEY>";
            end[NO_AOP]*/
        }

    }
}
